"""
爬虫：自动化的加强版的浏览器
爬虫代码运行的过程，就是伪装自己是一个浏览器，骗取服务器获得数据的过程
数据包括三类：
（1）文本类 html（网页结构） css（样式） js（动作）response.text
（2）二进制文件 音频 视频 response.content
（3）配置文件 json格式 response.json()
"""
"""
举例：访问豆瓣电影top250
不同页的地址的区别：
第1页：https://movie.douban.com/top250?start=0&filter=
第2页：https://movie.douban.com/top250?start=25&filter=
第3页：https://movie.douban.com/top250?start=50&filter=
第n页：https://movie.douban.com/top250?start=(n-1)*25&filter=
"""

# 模拟请求的库：requests
# 解析返回的html的库：lxml
# 另外还有常用的解析库 BeautifulSoup pyquery
# 另外，re库不但可以解析html代码，还可以解析所有字符串，包括配置文件

# 安装:cmd方式
# pip install requests lxml -i https://pypi.tuna.tsinghua.edu.cn/simple/
import pandas as pd
import params
import requests
import time
from lxml import etree


def get_movie_url(url, header):
    """
    获取某个页面的25个电影的url
    :param url: 页面地址
    :param header: 请求头
    :return: 返回包含25个电影url的列表
    """
    response = requests.get(url,headers = header,timeout=2)
    html = response.text  # 获得相应结果的html代码
    # print(html)  # 从这里能发现电影名字和对应a标签的url地址
    r = etree.HTML(html)
    return r.xpath(params.xpath_movie_url)


def get_movie_info(url, header):
    """
    用于获取单个电影的详细信息
    :param url:当前电影的url
    :param header:请求头
    :return:返回当前url对应的电影的详细信息
    """
    movie_info = {} #空字典
    # 1 模拟请求 相当于在浏览器的地址栏刷新
    response = requests.get(url,headers=header,timeout=5)
    # 2 解析返回的文本结果
    html = response.text
    r = etree.HTML(html)
    # (1)获取电影名字和上映年份
    info_list = r.xpath(params.xpath_movie_name_year)
    # print(info_list)#['肖申克的救赎 The Shawshank Redemption', '(1994)']
    movie_info["电影名称"] = info_list[0]
    movie_info["上映年份"] = info_list[1][1:-1] # [1:-1]去掉左右两边括号
    # (2)获取主要背景信息 导演,编剧,主演...
    info_list = r.xpath(params.xpath_main_info)
    info_str = "".join(info_list).strip().replace(" ","")
    for line in info_str.split("\n"):
        if ":" in line:
            l = line.split(":")
            key = l[0]
            value = l[1]
            movie_info[key] = value
    # (3) 获取评分及评价人数
    info_list = r.xpath(params.xpath_score_count)
    info_list = [info for info in info_list if "\n" not in info]
    movie_info["评分"] = info_list[0]
    movie_info["评价人数"] = info_list[1]

    # 返回包含当前电影信息的字典
    return movie_info
def get_one_page_info(page):
    """
    获得本页对应的所有电影信息
    :param page: 代表页数
    :return: 返回当前页的所有电影信息
    """
    # 1 设置参数：url 请求头
    # 2 模拟浏览器请求 requests库
    # 3 解析返回的数据，得到25个电影的url
    # 4 循环25个电影url，依次模拟请求，得到某个电影的信息
    url = f"{params.main_url}?start={(page-1)*25}&filter="
    header = {}
    l = params.header_str.split(":")
    key = l[0]
    value = l[1]
    header[key] = value
    # print(url,header)
    url_list = get_movie_url(url,header)
    # 至此 得到了当前页面的25个电影的url
    info_list = []  # 用于保存当前页面的25个电影的详细信息
    # ==========使用一个电影作为测试=================
    # url_list = ["https://movie.douban.com/subject/1292052/"]
    index = 1  # 代表当前电影是第几个
    for url in url_list:
        # 得到当前这个电影的详细信息
        print(f"开始获取第{page}页的第{index}部电影...")
        result = get_movie_info(url,header)
        info_list.append(result)
        index += 1
    return info_list

def main(pages=10):
    """
    程序主函数
    :param pages: 一共爬取页数
    :return: 返回所有页对应的电影信息
    """
    movie_info_list = []
    for page in range(1, pages + 1):
        result = get_one_page_info(page)
        movie_info_list.extend(result)
    # 把最后的结果一次性保存到一个excel中：大列表包含多个字典
    df = pd.DataFrame(movie_info_list)
    df.to_excel("豆瓣电影TOP250结果.xlsx")


if __name__ == '__main__':
    time1 = time.time()  # 时间点1
    # print(main(pages=1)) # main函数定义了一个默认参数pages，可以传参：数字或pages=数字
    main(pages=1) # main函数定义了一个默认参数pages，可以传参：数字或pages=数字
    time2 = time.time()  # 时间点2
    print(f"程序总共运行了{int(time2 - time1)}秒")
